package me.toalec.RankUp.Permissions;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import me.toalec.RankUp.util.Utility;

import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.util.config.ConfigurationNode;


import com.platymuus.bukkit.permissions.PermissionsPlugin;

public class PermissionsBukkit extends PermissionsBase{
	
	PermissionsBukkit(Plugin instance){
		
		pp = (PermissionsPlugin)instance.getServer().getPluginManager().getPlugin("PermissionsBukkit");
		Utility.printConsole("PermissionsBukkit initialized!");
	}

	@Override
	boolean hasPermission(Player player, String node) {
		return player.hasPermission(node);
	}

	@Override
	boolean isValidPlayer(String playerName, Player worldReference) {
		return (pp.getPlayerInfo(playerName) != null);
	}

	@Override
	boolean isValidGroup(String groupName, Player worldReference) {
		return (groupName != null && pp.getGroup(groupName) != null);
	}

	@Override
	ArrayList<String> getGroupName(String playerName, Player worldReference) {
		ArrayList<String> str = new ArrayList<String>();
		List<com.platymuus.bukkit.permissions.Group> groupList = pp.getGroups(playerName);
		Iterator<com.platymuus.bukkit.permissions.Group> itr = groupList.iterator();
		while(itr.hasNext()){
			str.add( ((com.platymuus.bukkit.permissions.Group)itr.next()).getName());
		}
		return str;
	}

	@Override
	void removeGroup(String playerName, Player worldReference, String startingGroup) {
		try{
			List<String> list = getNode("users." + playerName).getStringList("groups", new ArrayList<String>());
			if(list.contains(startingGroup)){
				list.remove(startingGroup);
				getNode("users." + playerName).setProperty("groups", list);   
		        refreshPermissions();
			}
		}catch(Exception e){
			Utility.printConsole("Error removing " + playerName + " from " + startingGroup + ".");
		}
		
	}

	@Override
	void addGroup(String playerName, Player worldReference, String endingGroup) {
		try{
			List<String> list = getNode("users." + playerName).getStringList("groups", new ArrayList<String>());
			if(!list.contains(endingGroup)){
		        list.add(endingGroup);
		        getNode("users." + playerName).setProperty("groups", list);
		        refreshPermissions();
			}
		}catch(Exception e){
			Utility.printConsole("Error adding " + playerName + " from " + endingGroup + ".");
		}
	}
	
	@Override
	void addPermission(Player player, String node) {
		String rootNode = "permissions";
		if (node.contains(":")) {
            String world = node.substring(0, node.indexOf(':'));
            node = node.substring(node.indexOf(':') + 1);
            rootNode = "worlds." + world;
        }
		try{
		if (getNode("users." + player.getName() + "." + rootNode) == null) {
			createPlayerNode(player.getName(), rootNode);
        }
		
		Map<String, Object> list = getNode("users." + player.getName() + "." + rootNode).getAll();
        list.put(node, true);
        getNode("users." + player.getName()).setProperty(rootNode, list);
        
        refreshPermissions();
		}catch(Exception e){
			Utility.printConsole("Error adding permission " + node + " to " + player.getName() + ".");
			e.printStackTrace();
		}
	}
	
	void createPlayerNode(String playerName) throws SecurityException, NoSuchMethodException, ClassNotFoundException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException {
		if(pp.getPlayerInfo(playerName) == null){
			Method createPlayerNode = Class.forName("com.platymuus.bukkit.permissions.PermissionsCommand").getDeclaredMethod("createPlayerNode", String.class);
			Constructor<?> constructor = Class.forName("com.platymuus.bukkit.permissions.PermissionsCommand").getDeclaredConstructor(PermissionsPlugin.class);
			createPlayerNode.setAccessible(true);
			constructor.setAccessible(true);
			createPlayerNode.invoke(constructor.newInstance(pp), playerName);
			refreshPermissions();
		}
	}
	
	void createPlayerNode(String playerName, String node) throws SecurityException, NoSuchMethodException, ClassNotFoundException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException{
		Method createPlayerNode = Class.forName("com.platymuus.bukkit.permissions.PermissionsCommand").getDeclaredMethod("createPlayerNode", String.class, String.class);
		Constructor<?> constructor = Class.forName("com.platymuus.bukkit.permissions.PermissionsCommand").getDeclaredConstructor(PermissionsPlugin.class);
		createPlayerNode.setAccessible(true);
		constructor.setAccessible(true);
		createPlayerNode.invoke(constructor.newInstance(pp), playerName, node);
		refreshPermissions();
	}
	
	ConfigurationNode getNode(String node) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, SecurityException, NoSuchMethodException {
		Method getNode = pp.getClass().getDeclaredMethod("getNode", String.class);
		getNode.setAccessible(true);
		return ((ConfigurationNode)getNode.invoke(pp, node));
	}
	
	private void refreshPermissions() throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
		Method refreshPermissions = pp.getClass().getDeclaredMethod("refreshPermissions");
		refreshPermissions.setAccessible(true);
		refreshPermissions.invoke(pp);
	}
	
	private PermissionsPlugin pp;

}
